#include "processor.h"
#include "can_drv.h"
#include "can_hw.h"
#include "../cfg/canmsg_cfg.h"
#include "../pal/pal_mem.h"
#include "../can/can.h"
#include "../canid/canid.h"

can_message_handler can_message[NO_OF_CAN_MAILBOXES];
can_transmit_messages can_transmit_message[NO_OF_CAN_PORTS];
s16 no_mailboxes_used = 0;
can_receive_messages can_received_messages;
can_mailbox *current_message;





//--------------------------------------------------------------
/// \brief no_of_can_transmit_buffers_used
/// get number of transmit buffer used
/// \param[in]  port
/// \return     no of buffer used
//--------------------------------------------------------------
s16 no_of_can_transmit_buffers_used(s16 port)
{
    s16 pd_ret;
    if (can_transmit_message[port].in_ptr >= can_transmit_message[port].out_ptr)
    {   
        pd_ret = (can_transmit_message[port].in_ptr - can_transmit_message[port].out_ptr);
    }
    else
    {   
        pd_ret = ((U16)NO_OF_TRANSMIT_BUFFERS - can_transmit_message[port].out_ptr + can_transmit_message[port].in_ptr);
    }
    return pd_ret;
}
//--------------------------------------------------------------
/// \brief can_transmit_buffer_full
/// test if can transmit buffer is full
/// \param[in]  port
/// \return     0 not, 1 full
//--------------------------------------------------------------
s16 can_transmit_buffer_full(s16 port)
{
    return(no_of_can_transmit_buffers_used(port) >= (NO_OF_TRANSMIT_BUFFERS - 1));
}


/*
    assign a CAN mesage resource
    returns the mailbox id if any are available
    returns -1 if none are available or illegal function
*/
s16 assign_a_mailbox(s16 port)
{
    s16 new_mailbox;
    s16 pd_ret;
    if ((no_mailboxes_used < (NO_OF_CAN_MAILBOXES - NO_OF_CAN_PORTS)) && (port <= (NO_OF_CAN_PORTS - 1)))
    {
        /* Valid mailbox and function, assign a mailbox*/
        new_mailbox = no_mailboxes_used;
        no_mailboxes_used++;
        can_message[new_mailbox].port = port;
        set_mailbox_assigned_flag(new_mailbox);
        pd_ret = new_mailbox;
    }
    else
    {
        // no mailbox assigned
        pd_ret = -1;
    }
    return pd_ret;
}


//--------------------------------------------------------------
/// \brief send_can_message
/// Load messages to transmit into the transmit FIFO
/// \param[in]  mailbox
/// \return     0 fail, 1 success
//--------------------------------------------------------------
s16 send_can_message(can_mailbox *mailbox)
{ 
    if( (*mailbox).id.full == (U32)V_Trac_PDOF_TX)/*high priority, send at once*/
    {
        can_ext_mo_hi.can_mo_ptr->MOCTR = 0x00000020; 
        can_ext_mo_hi.can_mo_ptr->MODATAL = (*mailbox).store.u32data[0];
        can_ext_mo_hi.can_mo_ptr->MODATAH = (*mailbox).store.u32data[1];
        can_ext_mo_hi.can_mo_ptr->MOCTR = 0x07280040;
    }
    else
    {
        u16 *in_ptr = &can_transmit_message[(*mailbox).port].in_ptr;
        if((*mailbox).port == (u8)CAN_PORT_EXT)
        {
            can_transmit_message[CAN_PORT_EXT].buffer[*in_ptr].id.full = (*mailbox).id.full;
            can_transmit_message[CAN_PORT_EXT].buffer[*in_ptr].dlc = (*mailbox).dlc;
            can_transmit_message[CAN_PORT_EXT].buffer[*in_ptr].store.u32data[0] = (*mailbox).store.u32data[0];
            can_transmit_message[CAN_PORT_EXT].buffer[*in_ptr].store.u32data[1] = (*mailbox).store.u32data[1];
            (*in_ptr)++;
            (*in_ptr) &= NO_OF_TRANSMIT_BUFFERS - 1;
            if(can_port_ext_transmiting == 0)
            {
                transmit_can_messages_ext();
            }
        }

        else if((*mailbox).port == (u8)CAN_PORT_INT)
        {
            can_transmit_message[CAN_PORT_INT].buffer[*in_ptr].id.full = (*mailbox).id.full;
            can_transmit_message[CAN_PORT_INT].buffer[*in_ptr].dlc = (*mailbox).dlc;
            can_transmit_message[CAN_PORT_INT].buffer[*in_ptr].store.u32data[0] = (*mailbox).store.u32data[0];
            can_transmit_message[CAN_PORT_INT].buffer[*in_ptr].store.u32data[1] = (*mailbox).store.u32data[1];
            (*in_ptr)++;
            (*in_ptr) &= NO_OF_TRANSMIT_BUFFERS - 1;
            if(can_port_int_transmiting == 0)
            {
                transmit_can_messages_int();
            }
        }
        else
        {
            ;
        }
        
    }
    return(1);
}

/*
 Get the oldest message buffer in the mailbox requested
*/

can_mailbox *get_can_message(s16 mailbox_no)
{
    s16 outptr;
    can_message_buffer *buffer;
    can_mailbox *pd_ret = NULL;    
    buffer = &can_message[mailbox_no].buffer;
        
    if ((*buffer).out_ptr != (*buffer).in_ptr)
    {
        // Update buffer fifo output pointer
        outptr = (*buffer).out_ptr;
        (*buffer).out_ptr ++;
        if ((*buffer).out_ptr >= (U16)CAN_BUFFER_SIZE)
        {
            (*buffer).out_ptr = 0;
        }
            
        // Get the current message in current_mailbox
        pd_ret = &(*buffer).mailbox[outptr];
    }
    return pd_ret;
}



/* Check for a recieved message in the Receive FIFO and return the mailbox no
*/
static s16 do_we_have_a_message(void)
{
    s16 current_mailbox;
    s16 pd_ret = -1;
    if (can_received_messages.out_ptr != can_received_messages.in_ptr)
    {
        // get the current mailbox and update FIFO pointer
        current_mailbox = can_received_messages.mail_box[can_received_messages.out_ptr];
        can_received_messages.out_ptr++;
        if (can_received_messages.out_ptr >= (U16)MESSAGE_RECEIVED_BUFFER_SIZE)
        {
            can_received_messages.out_ptr = 0;
        }
        pd_ret = current_mailbox;
    }
    return pd_ret;
}


/*
  Mailbox message Dispatcher
  Check the meassge fifo to see if any pending messages are present.
  Pull each message present from the FIFO and process with the assigned message handler.
*/
void process_can_received_messages_tic()
{
    s16 current_mailbox;
    can_mailbox *message;
    
    while ((current_mailbox = do_we_have_a_message()) >= 0)
    {
        // Get the message data for this mailbox
        message = get_can_message(current_mailbox);
        current_message = message;
        can_process_message(message);
    }
}


